# -*- coding:utf-8 -*-
# @Author : mistchan
# @Time : 2023/3/19 0019 19:38
# @File : main.py
# @Software: PyCharm
import sys
import json, os, re
import traceback
from datetime import datetime
from PyQt5.QtCore import Qt, QMetaObject, QCoreApplication
from PyQt5.QtGui import QCursor, QShowEvent, QIcon, QKeySequence
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout, QHeaderView, QDialog
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableView,QLabel,QCheckBox,QButtonGroup,QSpacerItem, QAction, QSystemTrayIcon, QShortcut
from PyQt5.QtWidgets import QMessageBox, QMenu, QAbstractItemView, QFileDialog, QSizePolicy, QTextEdit, QGridLayout
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
from utils.threads import RenewThread, ShiftThread, RefreshAllThread, RunDipTh, DelThread, AddUpdateThread
from utils.dialog import InfoDialog, PatientInfoDialog
from utils.scheduler import SCHEDULER, ADDER
from utils import first_evaluate
from root import READY, RUNNING
from utils.tools import read_json, update_patient_info
from tool_dialogs import main_win_tool_dialogs
from docx import Document
from docx.oxml.ns import qn



class JbDialog(QDialog):
    # 鉴别诊断
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # self.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint)      
        self.setupUi()
        self.retranslateUi()
        self.setWindowTitle("鉴别诊断")
    def setupUi(self):
        self.verticalLayout_2 = QVBoxLayout(self)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
      
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        # 确定按钮
        self.pushButton_2 = QPushButton(self)
        self.pushButton_2.clicked.connect(self.submit)

        self.horizontalLayout.addWidget(self.pushButton_2)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout.addLayout(self.init_difdig())

        spacerItem1 = QSpacerItem(183, 14, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem1)

        self.zrcf_textEdit = QTextEdit(self)
        self.verticalLayout.addWidget(self.zrcf_textEdit)
        self.verticalLayout_2.addLayout(self.verticalLayout)

        self.retranslateUi()
        QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        _translate = QCoreApplication.translate
        self.setWindowTitle(_translate("Dialog", "Dialog"))
        self.pushButton_2.setText(_translate("Dialog", "确定"))

    def init_difdig(self):
        # 鉴别诊断
        difdigLayout = QGridLayout()
        self.difdig_detail = read_json("dif_diagnosis.json")
        difdig_list = read_json("dif_diagnosis_list.json")
        row = 0
        col = 0

        radio_button_list = []
        self.radio_button_difdig_group = radio_button_difdig_group = QButtonGroup(self)
        self.radio_button_difdig_group.setExclusive(False)
        

        for each in difdig_list:
            radio_button_list.append("space" if each == "space" else QCheckBox(each))

        for obj in radio_button_list:
            
            if obj == "space":
                row += 1
                col = 0
                continue
            else:

                # obj.toggled.connect(self.radio_checked_fn)
                difdigLayout.addWidget(obj, row, col, 1, 1)
                radio_button_difdig_group.addButton(obj)
                col += 1
                if col > 5:
                    col = 0
                    row += 1
        return difdigLayout

    def submit(self):
        result = ""
        n = 1
        for each in self.radio_button_difdig_group.buttons():
            if each.isChecked():
                
                difdig_selected = "%s、%s：%s；" %(n, each.text(), self.difdig_detail.get(each.text()))
                n += 1
                result += difdig_selected
        clipboard = QApplication.clipboard()

        clipboard.setText(result)
       
        self.zrcf_textEdit.setText(result)


class MainWindow(QWidget):
    def __init__(self):
        self.layout_shift = 3
        super().__init__()
        # 全局控件
        self.switch = READY
        self.txt_asin = None
        self.table_view = None
        # 窗体标题
        self.setWindowTitle("Doc.Chan's Tricks")
        self.setWindowIcon(QIcon("trash.png"))
        
        # 初始化系统托盘相关的对象和菜单项
        self._restore_action = QAction()
        self._quit_action = QAction()
        self._tray_icon_menu = QMenu()
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon("trash.png"))  # 替换为你的图标路径
        self.tray_icon.setToolTip("Doc.Chan's Tricks")

        self.create_actions()
        self.create_tray_icon()
        self.tray_icon.show()

        # 连接系统托盘图标的激活事件
        self.tray_icon.activated.connect(self.tray_icon_activated)

        # 应用程序键盘监听
        self.listen_keyboard()

        # 尺寸
        self.resize(900, 600)
        # 位置
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)

        # 创建布局
        layout = QVBoxLayout()

        layout.addLayout(self.init_header())

        layout.addLayout(self.init_form())

        layout.addLayout(self.init_table())

        layout.addLayout(self.init_footer())

        # 给窗体设置元素的排列方式
        self.setLayout(layout)
        
        self.old_hook = sys.excepthook
        sys.excepthook = self.error_win
        
    def showEvent(self, a0: QShowEvent) -> None:
        # 控件都渲染出来后再处理焦点问题
        self.txt_asin.setFocus()
        self.model.setSort(2, Qt.AscendingOrder)  #排序
        self.model.select()
        return super().showEvent(a0)
    # def closeEvent(self, event):
    #     # 退出确认
    #     reply = QMessageBox.question(self,u"警告", u"确认退出？", QMessageBox.Yes, QMessageBox.No)
    #     if reply == QMessageBox.Yes:
    #         event.accept()
    #     else:
    #         event.ignore()
    def minimize_to_tray(self):
        # 最小化窗口到系统托盘
        self.hide()

    def restore_from_tray(self):
        # 还原窗口
        if self.isMinimized():
            self.showNormal()
        elif self.isMaximized():
            self.showMaximized()
        else:
            self.show()

    def tray_icon_activated(self, reason):
        # 当系统托盘图标被点击时的处理
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            # 如果点击的是触发事件（比如左键单击），则还原窗口
            self.restore_from_tray()

    def create_actions(self):
        # 创建菜单项
        self._restore_action = QAction("显示", self)
        self._restore_action.triggered.connect(self.restore_from_tray)  # "显示"菜单项触发还原窗口的操作
        self._quit_action = QAction("退出", self)
        self._quit_action.triggered.connect(QApplication.quit)  # "退出"菜单项触发退出应用程序的操作

    def create_tray_icon(self):
        # 创建系统托盘图标和上下文菜单
        self._tray_icon_menu = QMenu(self)
        self._tray_icon_menu.addAction(self._restore_action)
        self._tray_icon_menu.addSeparator()
        self._tray_icon_menu.addAction(self._quit_action)
        self.tray_icon.setContextMenu(self._tray_icon_menu)
        self.tray_icon.show()

    def listen_keyboard(self):
        # 键盘监听
        shortcut = QShortcut(QKeySequence("Esc"), self)
        # 当按下 Esc 键时隐藏窗口
        shortcut.activated.connect(self.hide)
        
    def init_header(self):
        # 1.创建顶部菜单布局
        header_layout = QHBoxLayout()
        # 1.1创建两个按钮
        # btn_start = QPushButton('全部更新')
        # btn_start.clicked.connect(self.event_renew_all_click)
        # btn_start.clicked.connect(self.event_refresh_all)
        # header_layout.addWidget(btn_start)

        btn_stop = QPushButton('导入新病人')
        btn_stop.clicked.connect(self.add_new_file)
        header_layout.addWidget(btn_stop)

        btn_reset = QPushButton('在院病人')
        btn_reset.clicked.connect(self.event_reset_click)
        header_layout.addWidget(btn_reset)
        btn_out = QPushButton('出院病人')
        btn_out.clicked.connect(self.event_out)
        header_layout.addWidget(btn_out)

        btn_shift = QPushButton('交班报告')
        btn_shift.clicked.connect(self.event_shift)
        header_layout.addWidget(btn_shift)
        btn_dip = QPushButton('DIP')
        btn_dip.clicked.connect(self.event_dip)
        header_layout.addWidget(btn_dip)
        btn_tools = QPushButton('tools')
        btn_tools.clicked.connect(self.event_tools)
        header_layout.addWidget(btn_tools)
        # 1.2添加弹簧
        header_layout.addStretch()
        self.btn_switch = btn_switch = QPushButton('内容布局')
        btn_switch.clicked.connect(self.event_switch_click)
        header_layout.addWidget(btn_switch)
        self.btn_hide = btn_hide = QPushButton('隐藏')
        btn_hide.clicked.connect(self.event_hide_click)
        header_layout.addWidget(btn_hide)
        return header_layout

    def event_dip(self):
        thread = RunDipTh(self)
       

        thread.start()
    def event_tools(self):
        dialog = main_win_tool_dialogs.ToolsDialog(self)        
        dialog.setWindowModality(Qt.ApplicationModal)
        dialog.exec_()
    def event_hide_click(self):
        # 最小化到托盘
        self.hide()

    def event_switch_click(self):
  
        result = self.layout_shift % 3
        self.layout_shift += 1
        if result == 0:
            self.btn_switch.setText('紧凑布局')
            self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        elif result == 1:
            self.btn_switch.setText('自由布局')
            self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
        else:
            self.btn_switch.setText('内容布局')
            self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.btn_switch.repaint()


    def init_form(self):
        # 2.创建上边标题布局
        form_layout = QHBoxLayout()
        # 2.1输入框
        txt_asin = QLineEdit()
        txt_asin.setPlaceholderText("1、模糊查询：请输入住院号或姓名；2、添加病人请输入住院号后回车，批量添加用空格隔开；3、交班报告输入住院号后点击对应功能。")
        # 点击回车键
        txt_asin.returnPressed.connect(self.add_new)
        
        self.txt_asin = txt_asin
        txt_asin.textChanged.connect(self.search_content)

        form_layout.addWidget(txt_asin)
        

        # 2.2添加按钮
        btn_add = QPushButton('添加')
        btn_add.clicked.connect(self.add_new)

        form_layout.addWidget(btn_add)
        return form_layout

    def init_table(self):

        # 3.创建中间表格布局
        self.table_layout = QHBoxLayout()
        # 3.1创建表格
        self.table_view = table_widget = QTableView()
        if not os.path.exists('.\\DB\\data.db'):
            self.init_sql()
        con = QSqlDatabase.addDatabase('QSQLITE')

        con.setDatabaseName('.\\DB\\data.db')
        if not con.open():
            print(con.lastError().text())
            return
        self.model = QSqlTableModel(self)
        self.model.setTable('patients')
        # self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
        today = datetime.today().strftime("%Y.%m.%d")
        self.model.setFilter("(出院日期=='无信息' or 出院日期>='%s' or 出院日期=='None') and del_flag==0" % today)
        # self.model.setSort(2, Qt.AscendingOrder)  #排序
        self.model.select()
        font = self.table_view.horizontalHeader().font()  # 获取当前表头的字体
        font.setFamily("微软雅黑")  # 修改字体设置
        self.table_view.horizontalHeader().setFont(font)  # 重新设置表头的字体

        # self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
        self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        # 禁止编辑
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_view.doubleClicked.connect(self.show_info)
        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)  # 设置策略为自定义菜单
        self.table_view.customContextMenuRequested.connect(self.ContextMenu)  # 菜单内容回应信号槽
        self.table_view.setModel(self.model)
        self.table_view.setSortingEnabled(True)
        for i in range(self.model.columnCount()):
            if i in [0, 13,]:
                self.table_view.setColumnHidden(i, True)

        self.table_layout.addWidget(table_widget)
        return self.table_layout

    def init_footer(self):
        # 4.创建底部菜单布局
        footer_layout = QHBoxLayout()
        # 4.1状态条
        self.label_status = label_status = QLabel('无运行任务')
        footer_layout.addWidget(label_status)
        # 占位弹簧
        footer_layout.addStretch()
        # 4.2按钮
        # btn_brxx = QPushButton('填写病人信息')
        # btn_brxx.clicked.connect(self.fill_patient_info)
        # footer_layout.addWidget(btn_brxx)

        # btn_scpg = QPushButton('自动首次评估')
        # btn_scpg.clicked.connect(self.first_evaluate)
        # footer_layout.addWidget(btn_scpg)

        # btn_bed = QPushButton('更新床号')
        # btn_bed.clicked.connect(self.update_bad)
        # footer_layout.addWidget(btn_bed)
        btn_jbzd = QPushButton('鉴别诊断')
        btn_jbzd.clicked.connect(self.jbzd)
        footer_layout.addWidget(btn_jbzd)
        btn_cf_local = QPushButton('查房打印')
        btn_cf_local.clicked.connect(self.patient_list_local)
        footer_layout.addWidget(btn_cf_local)

        btn_bc = QPushButton('初始化数据库')
        btn_bc.clicked.connect(self.init_sql)
        footer_layout.addWidget(btn_bc)
        return footer_layout

    # 点击全部更新
    def event_renew_all_click(self):
        if self.switch != READY:
            QMessageBox.critical(self, "错误！", "程序正在运行中，无法完成操作！")
            return
        self.switch = RUNNING
        self.update_status_msg("正在更新全部数据...")
        SCHEDULER.start(
            self,  # 窗体
            self.task_start_callback,
            self.spider_success_callback,
            self.spider_error_callback,

        )

    def event_refresh_all(self):
        if self.switch != READY:
            QMessageBox.critical(self, "错误！", "程序正在运行中，无法完成操作！")
            return
        self.switch = RUNNING
        self.thread = RefreshAllThread(self)
        self.thread.success.connect(self.spider_success_callback)
        self.thread.status.connect(self.spider_status_callback)
        self.thread.error.connect(self.spider_error_callback)
        self.thread.finish.connect(self.spider_finish_callback)

        self.thread.start()

    def task_start_callback(self, row_index):
        # 对表格某行的状态进行更新

        pass

        # 查询

    def search_content(self):

        keywords = self.txt_asin.text().strip()
        if keywords:

            self.model.setFilter("住院号||姓名 like '%{}%'".format(keywords))
            self.model.select()

            self.table_view.setModel(self.model)
        else:
            today = datetime.today().strftime("%Y.%m.%d")
            self.model.setFilter("出院日期=='无信息' or 出院日期>='%s' and del_flag==0" % today)
            self.model.select()
            self.table_view.setModel(self.model)

    def event_reset_click(self):
        # 点击刷新按钮 在院病人列表
        today = datetime.today().strftime("%Y.%m.%d")
        self.model.setFilter("出院日期=='无信息' or 出院日期>='%s' and del_flag==0" % today)
        self.model.select()
        self.table_view.setModel(self.model)

    def event_out(self):
        # 点击刷新按钮 出院病人列表
        today = datetime.today().strftime("%Y.%m.%d")
        self.model.setFilter("出院日期<='%s' and del_flag==0" % today)
        self.model.select()
        self.table_view.setModel(self.model)
    def spider_finish_callback(self, index):
        self.switch = READY
        self.model.select()
        self.table_view.setModel(self.model)
        self.update_status_msg(f"全部更新成功！")
    def spider_success_callback(self, index, result_dic):        
        self.update_status_msg(f"第{index + 1}行更新成功！")
                
    def spider_status_callback(self, index):
        
        self.update_status_msg(f"开始更新第{index + 1}行...")
    def spider_error_callback(self, index, error, ):
        self.update_status_msg(f"更新失败：{error}")
    
    def info_renew_error_callback(self, error):
        self.switch = READY
        self.update_status_msg(f"更新失败：{error}")
    def event_shift(self):
        # 交班
        pid_list = self.txt_asin.text().split()
        
        # file_path = "E:\\RjDir\\UserData\\Desktop\\1.txt"
        thread = ShiftThread(pid_list, self)
        thread.success.connect(self.shift_success_callback)
        thread.status.connect(self.shift_status_callback)
        thread.error.connect(self.shift_error_callback)

        thread.start()

    def shift_success_callback(self, cur_date, file_kind, random_file_name):
        #自动合并交班本
        try:
            with open("myjson\\交班本路径.json", 'r', encoding='utf-8') as f_jbb:
                url = json.load(f_jbb) 
            url= url.get('url')
        
        except Exception as e:
            url = None
            while not os.path.isfile(url):
                # 设置文件扩展名过滤,注意用双分号间隔
                new_url, filetype = QFileDialog.getOpenFileName(self, "交班本路径不存在，请选择：", "\\\\10.68.113.211\\共享文件\\★★交班本\\", "Word 文档 (*.docx);;所有文件 (*)")       

                url = new_url 
        
        while not os.path.isfile(url):
            # 设置文件扩展名过滤,注意用双分号间隔
            new_url, filetype = QFileDialog.getOpenFileName(self, "请选择合并到哪个word文件", "\\\\10.68.113.211\\共享文件\\★★交班本\\", "Word 文档 (*.docx);;所有文件 (*)")       

            url = new_url if new_url else url
        while True:
            asks = QMessageBox.question(self, "注意", "是否合并到%s"%url, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
            if asks == 16384:
                break
            else:
                new_url, filetype = QFileDialog.getOpenFileName(self, "请选择合并到哪个word文件", "\\\\10.68.113.211\\共享文件\\★★交班本\\", "Word 文档 (*.docx);;所有文件 (*)")       

                url = new_url if new_url else url
        with open("myjson\\交班本路径.json", 'w', encoding='utf-8') as f_rn:
            json.dump({"url": url}, f_rn, ensure_ascii=False)
        from docxcompose.composer import Composer
        doc_m = Document(url)
        shift_mod = Document('.\\交班报告\\%s%s%s.docx' % (cur_date, file_kind, random_file_name))
        cp = Composer(doc_m)
        cp.append(shift_mod)
        while True:
            try:
                doc_m.save(url)
                QMessageBox.information(self, "成功", "合并成功！")
                return
            except Exception as e:
                QMessageBox.critical(self, "出错", f"{e}！")
                continue
            
        

    def shift_status_callback(self, status):
        self.update_status_msg(f"{status}")
        
    def shift_error_callback(self, error):
        self.update_status_msg(f"运行出错：{error}")
        
    def add_new(self):
        pid_list = self.txt_asin.text().split()
        
        ADDER.start(
            self,  # 窗体
            pid_list,
            self.add_new_success_callback,
            self.add_new_error_callback,

        )

    def add_new_success_callback(self, result_dic):
        self.model.select()
        self.table_view.setModel(self.model)

        self.switch = READY
        self.txt_asin.clear()
        # 弹出病人详细情况
        pid = result_dic.get("住院号")
        name = result_dic.get("姓名")
        sex = result_dic.get("性别")
        age = result_dic.get("年龄")
        row = 0

        dialog = InfoDialog(pid, row, f"{pid} {name} {sex} {age}", self)
        dialog.setWindowModality(Qt.ApplicationModal)
        dialog.exec_()


    def add_new_error_callback(self, error, ):
        self.update_status_msg(f"更新失败：{error}")

    def show_info(self, item=None):
        # 点击住院号显示操作
        if item is None:
            return
        else:

            row = item.row()
            # col = item.column()
            try:
                pid = self.table_view.model().index(row, 1).data()

                name = self.table_view.model().index(row, 3).data()
                sex = self.table_view.model().index(row, 4).data()
                age = self.table_view.model().index(row, 5).data()
            except Exception as e:
                return
            dialog = InfoDialog(pid, row, f"{pid} {name} {sex} {age}", self)
            dialog.setWindowModality(Qt.ApplicationModal)
            dialog.exec_()
    def deled_callback(self, s):
        self.switch = READY
        self.model.select()
        self.table_view.setModel(self.model)
        self.update_status_msg(f"操作成功！")
    def ContextMenu(self, pos):
        # 表格上的右键菜单
        row = self.table_view.currentIndex().row()  # 获取被选择的行数
        model = self.table_view.model()  # 获取被选择的模型
        pos = self.table_view.mapFromGlobal(QCursor.pos())  # 获取表格中鼠标坐标
        it = self.table_view.columnAt(pos.x())  # 根据鼠标坐标获取列号
        Comp = model.index(row, it).data()  # 根据模型获取第row行第it列(从0开始算第1列)的内容
        menu = QMenu()

        item_fresh = menu.addAction("更新")
        item_shift = menu.addAction("交班")
        item_add = menu.addAction("添加到输入框")
        item_copy = menu.addAction("复制")
        item_del = menu.addAction("删除")
        item_rewind = menu.addAction("恢复")

        action = menu.exec_(self.table_view.mapToGlobal(pos))
        if action == item_copy:  # 复制功能

            clipboard = QApplication.clipboard()
            text_copied = Comp
            clipboard.setText(text_copied)
            self.update_status_msg(f"【{text_copied}】已复制到剪贴板")

        if action == item_shift:  # 交班功能
            
            row_selected = [row.row() for row in self.table_view.selectedIndexes()]
            
            patients = [model.index(row, 3).data() for row in row_selected]
            
            reply = QMessageBox.question(self,u"正在运行交班程序", u"交班的新病人：%s" % "，".join(patients), QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
            
                pid_list = [model.index(row, 1).data() for row in row_selected]
                thread = ShiftThread(pid_list, self)
                thread.success.connect(self.shift_success_callback)
                thread.error.connect(self.shift_error_callback)

                thread.start()
            else:
                return
            
        if action == item_add:  # 添加功能
            
            row_selected = [row.row() for row in self.table_view.selectedIndexes()]
            
           
            pids =" ".join([model.index(row, 1).data() for row in row_selected])

            self.txt_asin.setText(pids)
        
        if action == item_fresh:
            if self.switch != READY:
                QMessageBox.critical(self, "错误！", "程序正在运行中，无法完成操作！")
                return

            self.switch = RUNNING
            pid = self.table_view.model().index(row, 1).data()
            self.update_status_msg(f"正在更新第{row + 1}行：{pid}")
            thread = RenewThread(pid, row, self)
            thread.success.connect(self.spider_success_callback)
            thread.error.connect(self.info_renew_error_callback)

            # 线程开始
            thread.start()
            
        if action == item_del:
            pid = self.table_view.model().index(row, 1).data()
            if self.switch != READY:
                QMessageBox.critical(self, "错误！", "程序正在运行中，无法完成操作！")
                return
            reply = QMessageBox.question(self,u"警告", u"确认删除？", QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
            
                thread = DelThread(pid, row, 1, self)
                thread.success.connect(self.deled_callback)
                thread.error.connect(self.info_renew_error_callback)
                # 线程开始
                thread.start()
            else:
                return
        
        if action == item_rewind:
            pid = self.table_view.model().index(row, 1).data()
            if self.switch != READY:
                QMessageBox.critical(self, "错误！", "程序正在运行中，无法完成操作！")
                return
            reply = QMessageBox.question(self,u"警告", u"确认恢复？", QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
            
                thread = DelThread(pid, row,0, self)
                thread.success.connect(self.deled_callback)
                thread.error.connect(self.info_renew_error_callback)
                # 线程开始
                thread.start()
            else:
                return
        
        
    def update_status_msg(self, msg):
        if msg == "无活动程序":
            self.switch = READY
        self.label_status.setText(msg)
        self.label_status.repaint()

    def init_sql(self):
        # 初始化数据库

        db = QSqlDatabase.addDatabase('QSQLITE')  # 指定数据库类型
        # 指定SQLite数据库文件名
        db.setDatabaseName('.\\DB\\data.db')  # muttonDB.db之前的目录都要存在才可建立成功！数据库名字自己随便起
        if not db.open():
            QMessageBox.critical(self, "错误！", "无法建立与数据库的连接！")
            return
        query = QSqlQuery()
        query.exec('SELECT name FROM sqlite_master WHERE name="patients"')
        query.first()
        if query.value(0):
            QMessageBox.information(self, "操作已取消", "数据表已存在，无需初始化。")
        else:
            with open('.\\DB\\key_words_sql.json', 'r', encoding='utf8') as fk:
                key_words_sql = json.load(fk)
            sql_ = ", ".join(key_words_sql)
            sql_ = f'create table patients (`id` INTEGER PRIMARY KEY, {sql_})'

            query.exec(sql_)

            QMessageBox.information(self, "成功", "数据库已完成初始化。")

        db.close()

    def add_new_file(self):
        info_dict = update_patient_info("")

        thread = AddUpdateThread(info_dict, self)
        thread.success.connect(self.add_new_success_callback)
        thread.error.connect(self.add_new_error_callback)
           
        thread.start()

    def fill_patient_info(self):
        # 自动填写病人信息
        
        patient_info = read_json("patient_info.json")
        dialog = PatientInfoDialog(patient_info)
        
        dialog.setWindowModality(Qt.ApplicationModal)
        self.setWindowState(Qt.WindowMinimized)
        dialog.exec_()
        
    

    def first_evaluate(self):
        # 窗口最小化
        self.setWindowState(Qt.WindowMinimized)
        first_evaluate.run()


    def patient_list_local(self):
        
        
        data_list = [json.loads(self.table_view.model().index(index, 13).data()) for index in range(self.table_view.model().rowCount())]
        data_list = sorted(data_list, key=lambda x: x["床号"])
        doc = Document()
        idx = 1
        now_a_days = datetime.today().strftime("%Y-%m-%d")
        p = doc.add_paragraph()
        p.add_run(f"{now_a_days}").bold = True
        for patient_info in data_list:

           
            pid = patient_info.get('住院号', "")              
                
            in_date_ = patient_info.get("入院时间").split()[0]
            if in_date_:
                in_date = datetime.strptime(in_date_, "%Y-%m-%d")
                in_day = in_date.strftime("%m.%d")
                days_count = (datetime.today() - in_date).days
            else:
                in_day = days_count = ""
            patient = "%s %s %s %s %s(%s天)%s" % (
                patient_info.get('床号', ""),
                patient_info.get('姓名', ""),
                patient_info.get('性别', ""),
                patient_info.get('年龄', ""),
                in_day,
                days_count,
                pid,
            )
            chief_complaint = patient_info.get('主诉', "")
            final_diagnosis = patient_info.get('出院诊断', "")
            diag = final_diagnosis if final_diagnosis not in ("无信息",None, "None", "") else patient_info.get('诊断', "")
            diag = diag if diag not in ("无信息",None, "None",) else ""
            test_res = patient_info.get('化验单', "")
            test_result = ""
            for name, unit, sx in [
                ["肺炎支原体", "[Au/mL]*", "支(20)"],
                ["肺炎衣原体", "[Au/mL]*", "衣(20)"],
                ["维生素D", "ng/mL", "VD"],
                ["降钙素原", "ng/ml", "PCT"],
                ["白细胞计数", "10\^9/L", "WBC"],
                ["粒细胞", "10\^9/L", "sg"],
            ]:
                result = re.search(f"{name}(.*?\s)([0-9.阳阴性↑]+)\s{unit}", test_res)
                
                if result:
                    test_result += f"{sx} {result.group(2)}；"

            image_res = patient_info.get('影像学', '') if patient_info.get('影像学', '') not in ("无信息",None, "None",) else "" 
            
            p = doc.add_paragraph()
            p.add_run(f"【{idx}】{patient}").bold = True
            p.add_run('\n主诉：' + chief_complaint + "。 诊断：" + diag)
            p.add_run('\n' + test_result + image_res)
            idx += 1
            doc.styles["Normal"].font.name = 'Times New Roman'
            doc.styles["Normal"]._element.rPr.rFonts.set(qn('w:eastAsia'), u'微软雅黑')
                    
                
                                           
        doc.save('done.docx')
        os.startfile('done.docx')

    def update_bad(self):
        try:
            bed_list = read_patient(index=0)
            pid_list = [int(pid) for pid in read_patient(index=25)]
        except Exception as e:
            QMessageBox.critical(self, "错误！", "{}".format(e))
            return
        bed_pid = dict(zip(pid_list, bed_list))
        for index in range(self.table_view.model().rowCount()):
            pid = int(self.table_view.model().index(index, 1).data())
            self.table_view.model().setData(self.table_view.model().index(index, 2), bed_pid.get(pid))
                               
            self.table_view.model().submitAll()
            self.model.select()
            self.table_view.setModel(self.model)

    def error_win(self, ty,vals, tracebk):
        # 全局捕获异常，弹窗提示，避免程序因异常关闭
        tracebk_format = traceback.format_exception(ty, vals, tracebk)
        
        tracbk_string = f"{tracebk_format[-1]}"
        QMessageBox.critical(self, "运行出错!", f"程序运行时出现了一个致命错误!\n请联系管理员解决。\n详细错误信息：\n{tracbk_string}")
        # print(f"程序运行时出现了一个致命错误!\n请联系管理员解决。\n详细错误信息：\n{tracbk_string}")
        
        self.old_hook(ty, vals, tracebk)
        
    # def error_win(self, ty,vals, tracebk):
    #     pass
    
    def jbzd(self):
        dialog = JbDialog(self)        
        dialog.setWindowModality(Qt.ApplicationModal)
        dialog.exec_()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
